<?php
/**
 *  TinyMVC - MysqlDAO.class.php file
 * 
 * @author Adrian Wieczorek <adi(at)tinymvc(dot)org>
 * @package TinyMVC
 * @subpackage Database
 * @version $Id: MysqlDAO.class.php 3 2007-09-11 12:08:07Z adi3ek $
 * 
 */
 
/**
 * simple DAO class compatibile with MysqlDriver, descendant example class:
 * 
 * <code>
 * class Foo extends MysqlDAO {
 *
 *  public function __construct($id = 0) {
	*   self::$objectName = 'Foo';
	*   $this->tableName = 'foo_table';
	*   $this->priKeyField = 'ft_id';		
	*  	
	*   // parent constructor call
	*   parent::__construct($id);
	*  }
	* 
 * }
 * </code>
 * 
 * @package TinyMVC
 * @subpackage Database
 */
abstract class MysqlDAO {
	protected $id;
	protected $db;
	protected $priKeyField;
	protected $tableName;
	protected $fields = array();
	protected static $objectName;
	
	/**
	 * @param int $id object unique id, usually = PRIMARY KEY
	 * @return MysqlDAO DAO object
	 */
	public function __construct($id = 0) {
		$this->db = Database::getInstance();

		if($id) {
			$this->feed($id);
		}
	}
	
	/**
	 * get object unique ID, usually = PRIMARY KEY
	 * @return int unique ID
	 */
	public function getId() {
		return $this->id;
	}
	
	/**
	 * get list of objects for given search criteria
	 * @param string $whereSqlStatement "where" SQL statement
	 * @todo make it static, different method of object instantiating
	 */
	public function getList($whereSqlStatement = "") {
		$list = array();

		$result = $this->db->query("SELECT " . $this->priKeyField . " FROM " . $this->tableName . (!empty($whereSqlStatement)?" WHERE $whereSqlStatement":""));
		while($row = $result->getNextRow()) {
			$objectName = get_class($this);
			$list[] = new	$objectName($row[$this->priKeyField]);
		}
		return $list;
	}
	
	/**
	 * get all fields
	 * @return array field => value array
	 */
	public function getFields() {
		return $this->fields;
	}
	
	/**
	 * get value for given field
	 * @param string $field field name
	 * @return string field value
	 */
	public function get($field) {
		return $this->fields[$field];
	}
	
	/**
	 * set field value
	 * @param string $field field name
	 * @param string $value field value
	 * 
	 */
	public function set($field, $value) {
		$this->fields[$field] = $value;
	}
	
	private function feed($id) {
		$result = $this->db->query("SELECT * FROM " . $this->tableName . " WHERE " . $this->priKeyField . "='" . addslashes($id) . "'");
		while($row = $result->getNextRow()) {
			$this->id = $row[$this->priKeyField];
			// TODO: check MysqlResult for int field names
			foreach($row as $field => $value) {
				if(($field != $this->priKeyField) && !is_int($field)) {
					$this->fields[$field] = $value;
				}
			}
		}
	}
	
	/**
	 * update or create object in database
	 */
	public function update() {
		if($this->id) {
			foreach($this->fields as $name => $value) {
				$update .= ($update ? ',' : 'SET ') . $name . "='" . addslashes($value) . "'";
			}
			$query = "UPDATE " . $this->tableName . " " . $update . " WHERE " . $this->priKeyField . "='" . $this->id . "'";
			$this->db->query($query);
		}
		else {
			$this->create();
		}
	}
	
	private function create() {
		foreach($this->fields as $name => $value) {
			$fields .= ($fields ? ',' : '') . $name;
			$values .= ($values ? ',' : '') . "'" . addslashes($value) . "'";
		}
		$query = "INSERT INTO " . $this->tableName . " ($fields) VALUES ($values)";
		$this->db->query($query);
		
		$result = $this->db->query("SELECT LAST_INSERT_ID() AS id");
		if($row = $result->getNextRow()) {
		 $this->id = $row['id'];
		}
		else {
			throw new TinyMVCException("MysqlDAO - last insert id has not been returned.");
		}
	}
	
	/**
	 * remove object from database
	 */
	public function delete() {
		if($this->id) {
			$this->db->query("DELETE FROM " . $this->tableName . " WHERE " . $this->priKeyField . "='" . $this->id . "'");
		}
	}
	
	/**
	 * alias: {@link delete}
	 */
	public function remove() {
		$this->delete();
	}
}
